home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / compress / unzip531.zip / unzip.c < prev    next >
C/C++ Source or Header  |  1997-05-13  |  57KB  |  1,612 lines

  1. /*---------------------------------------------------------------------------
  2.  
  3.   unzip.c
  4.  
  5.   UnZip - a zipfile extraction utility.  See below for make instructions, or
  6.   read the comments in Makefile and the various Contents files for more de-
  7.   tailed explanations.  To report a bug, send a *complete* description to
  8.   Zip-Bugs@lists.wku.edu; include machine type, operating system and ver-
  9.   sion, compiler and version, and reasonably detailed error messages or prob-
  10.   lem report.  To join Info-ZIP, see the instructions in README.
  11.  
  12.   UnZip 5.x is a greatly expanded and partially rewritten successor to 4.x,
  13.   which in turn was almost a complete rewrite of version 3.x.  For a detailed
  14.   revision history, see UnzpHist.zip at quest.jpl.nasa.gov.  For a list of
  15.   the many (near infinite) contributors, see "CONTRIBS" in the UnZip source
  16.   distribution.
  17.  
  18.   ---------------------------------------------------------------------------
  19.  
  20.   [from original zipinfo.c]
  21.  
  22.   This program reads great gobs of totally nifty information, including the
  23.   central directory stuff, from ZIP archives ("zipfiles" for short).  It
  24.   started as just a testbed for fooling with zipfiles, but at this point it
  25.   is actually a useful utility.  It also became the basis for the rewrite of
  26.   UnZip (3.16 -> 4.0), using the central directory for processing rather than
  27.   the individual (local) file headers.
  28.  
  29.   As of ZipInfo v2.0 and UnZip v5.1, the two programs are combined into one.
  30.   If the executable is named "unzip" (or "unzip.exe", depending), it behaves
  31.   like UnZip by default; if it is named "zipinfo" or "ii", it behaves like
  32.   ZipInfo.  The ZipInfo behavior may also be triggered by use of unzip's -Z
  33.   option; for example, "unzip -Z [zipinfo_options] archive.zip".
  34.  
  35.   Another dandy product from your buddies at Newtware!
  36.  
  37.   Author:  Greg Roelofs, newt@pobox.com, http://pobox.com/~newt/
  38.            23 August 1990 -> April 1997
  39.  
  40.   ---------------------------------------------------------------------------
  41.  
  42.   Version:  unzip53.{tar.Z | tar.gz | zip} for Unix, VMS, OS/2, MS-DOS, Amiga,
  43.               Atari, Windows 3.x/95/NT/CE, Macintosh, Human68K, Acorn RISC OS,
  44.               BeOS, SMS/QDOS, VM/CMS, MVS, AOS/VS and TOPS-20.  Decryption
  45.               requires sources in zcrypt27.zip.  See the accompanying "Where"
  46.               file in the main source distribution for ftp, uucp, BBS and mail-
  47.               server sites, or see http://www.cdrom.com/pub/infozip/UnZip.html .
  48.  
  49.   Copyrights:  see accompanying file "COPYING" in UnZip source distribution.
  50.                (This software is free but NOT IN THE PUBLIC DOMAIN.  There
  51.                are some restrictions on commercial use.)
  52.  
  53.   ---------------------------------------------------------------------------*/
  54.  
  55.  
  56.  
  57. #define UNZIP_C
  58. #define UNZIP_INTERNAL
  59. #include "unzip.h"        /* includes, typedefs, macros, prototypes, etc. */
  60. #include "crypt.h"
  61. #include "version.h"
  62. #ifdef USE_ZLIB
  63. #  include "zlib.h"
  64. #endif
  65.  
  66. #ifndef WINDLL            /* The WINDLL port uses windll/windll.c instead... */
  67.  
  68.  
  69. /*************/
  70. /* Constants */
  71. /*************/
  72.  
  73. #include "consts.h"  /* all constant global variables are in here */
  74.                      /* (non-constant globals were moved to globals.c) */
  75.  
  76. /* constant local variables: */
  77.  
  78. #ifndef SFX
  79.    static char Far EnvUnZip[] = ENV_UNZIP;
  80.    static char Far EnvUnZip2[] = ENV_UNZIP2;
  81.    static char Far EnvZipInfo[] = ENV_ZIPINFO;
  82.    static char Far EnvZipInfo2[] = ENV_ZIPINFO2;
  83. #ifdef RISCOS
  84.    static char Far EnvUnZipExts[] = ENV_UNZIPEXTS;
  85. #endif /* RISCOS */
  86. #endif
  87.  
  88. #if (!defined(SFX) || defined(SFX_EXDIR))
  89.    static char Far NotExtracting[] = "caution:  not extracting; -d ignored\n";
  90.    static char Far MustGiveExdir[] =
  91.      "error:  must specify directory to which to extract with -d option\n";
  92.    static char Far OnlyOneExdir[] =
  93.      "error:  -d option used more than once (only one exdir allowed)\n";
  94. #endif
  95.  
  96. #if CRYPT
  97.    static char Far MustGivePasswd[] =
  98.      "error:  must give decryption password with -P option\n";
  99. #endif
  100.  
  101. #ifndef SFX
  102.    static char Far Zfirst[] = 
  103.    "error:  -Z must be first option for ZipInfo mode (check UNZIP variable?)\n";
  104. #endif
  105. static char Far InvalidOptionsMsg[] = "error:\
  106.   -fn or any combination of -c, -l, -p, -t, -u and -v options invalid\n";
  107. static char Far IgnoreOOptionMsg[] =
  108.   "caution:  both -n and -o specified; ignoring -o\n";
  109.  
  110. /* usage() strings */
  111. #ifndef SFX
  112. #ifdef VMS
  113.    static char Far Example3[] = "vms.c";
  114.    static char Far Example2[] = "  unzip\
  115.  \"-V\" foo \"Bar\" => must quote uppercase options and filenames in VMS\n";
  116. #else /* !VMS */
  117.    static char Far Example3[] = "ReadMe";
  118. #ifdef RISCOS
  119.    static char Far Example2[] =
  120. "  unzip foo -d RAM:$   => extract all files from foo into RAMDisc\n";
  121. #else /* !RISCOS */
  122. #if defined(OS2) || (defined(DOS_OS2_W32) && defined(MORE))
  123.    static char Far Example2[] = "";   /* no room:  too many local3[] items */
  124. #else /* !OS2 */
  125.    static char Far Example2[] = " \
  126.  unzip -p foo | more  => send contents of foo.zip via pipe into program more\n";
  127. #endif /* ?OS2 */
  128. #endif /* ?RISCOS */
  129. #endif /* ?VMS */
  130.  
  131. /* local1[]:  command options */
  132. #if (defined(DLL) && defined(API_DOC))
  133.    static char Far local1[] = "  -A  print extended help for API functions";
  134. #else /* !(DLL && API_DOC) */
  135.    static char Far local1[] = "";
  136. #endif /* ?(DLL && API_DOC) */
  137.  
  138. /* local2[] and local3[]:  modifier options */
  139. #ifdef DOS_OS2_W32
  140.    static char Far local2[] = " -$  label removables (-$$ => fixed disks)";
  141. #ifdef OS2
  142. #ifdef MORE
  143.    static char Far local3[] = "\
  144.   -X  restore ACLs if supported              -s  spaces in filenames => '_'\n\
  145.                                              -M  pipe through \"more\" pager\n";
  146. #else
  147.    static char Far local3[] = " \
  148.  -X  restore ACLs if supported              -s  spaces in filenames => '_'\n\n";
  149. #endif /* ?MORE */
  150. #else /* !OS2 */
  151. #ifdef WIN32
  152. #ifdef MORE
  153.    static char Far local3[] = "\
  154.   -X  restore ACLs (-XX => use privileges)   -s  spaces in filenames => '_'\n\
  155.                                              -M  pipe through \"more\" pager\n";
  156. #else
  157.    static char Far local3[] = " \
  158.  -X  restore ACLs (-XX => use privileges)   -s  spaces in filenames => '_'\n\n";
  159. #endif /* ?MORE */
  160. #else /* !WIN32 */
  161. #ifdef MORE
  162.    static char Far local3[] = "  -\
  163. M  pipe through \"more\" pager              -s  spaces in filenames => '_'\n\n";
  164. #else
  165.    static char Far local3[] = "\
  166.                                              -s  spaces in filenames => '_'\n";
  167. #endif
  168. #endif /* ?WIN32 */
  169. #endif /* ?OS2 || ?WIN32 */
  170. #else /* !DOS_OS2_W32 */
  171. #ifdef VMS
  172.    static char Far local2[] = "\"-X\" restore owner/protection info";
  173. #ifdef MORE
  174.    static char Far local3[] = "  \
  175.                                           \"-M\" pipe through \"more\" pager\n";
  176. #else
  177.    static char Far local3[] = "\n";
  178. #endif
  179. #else /* !VMS */
  180. #ifdef UNIX
  181.    static char Far local2[] = " -X  restore UID/GID info";
  182. #ifdef MORE
  183.    static char Far local3[] = "\
  184.                                              -M  pipe through \"more\" pager\n";
  185. #else
  186.    static char Far local3[] = "\n";
  187. #endif
  188. #else /* !UNIX */
  189. #ifdef AMIGA
  190.     static char Far local2[] = " -N  restore comments as filenotes";
  191. #ifdef MORE
  192.     static char Far local3[] = "\
  193.                                              -M  pipe through \"more\" pager\n";
  194. #else
  195.     static char Far local3[] = "\n";
  196. #endif
  197. #else /* !AMIGA */
  198. #ifdef MORE
  199.     static char Far local2[] = " -M  pipe through \"more\" pager";
  200.     static char Far local3[] = "\n";
  201. #else
  202.     static char Far local2[] = "";   /* Atari, Mac, etc. */
  203.     static char Far local3[] = "";
  204. #endif
  205. #endif /* ?AMIGA */
  206. #endif /* ?UNIX */
  207. #endif /* ?VMS */
  208. #endif /* ?DOS_OS2_W32 */
  209. #endif /* !SFX */
  210.  
  211. #ifndef NO_ZIPINFO
  212. #ifdef VMS
  213.    static char Far ZipInfoExample[] = "* or % (e.g., \"*font-%.zip\")";
  214. #else
  215.    static char Far ZipInfoExample[] = "*, ?, [] (e.g., \"[a-j]*.zip\")";
  216. #endif
  217.  
  218. static char Far ZipInfoUsageLine1[] = "\
  219. ZipInfo %d.%d%d%s of %s, by Greg Roelofs and the fine folks at Info-ZIP.\n\
  220. \n\
  221. List name, date/time, attribute, size, compression method, etc., about files\n\
  222. in list (excluding those in xlist) contained in the specified .zip archive(s).\
  223. \n\"file[.zip]\" may be a wildcard name containing %s.\n\n\
  224.    usage:  zipinfo [-12smlvChMtTz] file[.zip] [list...] [-x xlist...]\n\
  225.       or:  unzip %s-Z%s [-12smlvChMtTz] file[.zip] [list...] [-x xlist...]\n";
  226.  
  227. static char Far ZipInfoUsageLine2[] = "\nmain\
  228.  listing-format options:             -s  short Unix \"ls -l\" format (def.)\n\
  229.   -1  filenames ONLY, one per line       -m  medium Unix \"ls -l\" format\n\
  230.   -2  just filenames but allow -h/-t/-z  -l  long Unix \"ls -l\" format\n\
  231.                                          -v  verbose, multi-page format\n";
  232.  
  233. static char Far ZipInfoUsageLine3[] = "miscellaneous options:\n\
  234.   -h  print header line       -t  print totals for listed files or for all\n\
  235.   -z  print zipfile comment  %c-T%c print file times in sortable decimal format\
  236. \n %c-C%c be case-insensitive   %s\
  237.   -x  exclude filenames that follow from listing\n";
  238. #ifdef MORE
  239. #ifdef VMS
  240.    static char Far ZipInfoUsageLine4[] =
  241.      " \"-M\" page output through built-in \"more\"\n";
  242. #else
  243.    static char Far ZipInfoUsageLine4[] =
  244.      "  -M  page output through built-in \"more\"\n";
  245. #endif
  246. #else /* !MORE */
  247.    static char Far ZipInfoUsageLine4[] = "";
  248. #endif /* ?MORE */
  249. #endif /* !NO_ZIPINFO */
  250.  
  251. #ifdef BETA
  252. #  ifdef VMSCLI
  253.    /* BetaVersion[] is also used in vms/cmdline.c:  do not make it static */
  254.      char Far BetaVersion[] = "%s\
  255.         THIS IS STILL A BETA VERSION OF UNZIP%s -- DO NOT DISTRIBUTE.\n\n";
  256. #  else
  257.      static char Far BetaVersion[] = "%s\
  258.         THIS IS STILL A BETA VERSION OF UNZIP%s -- DO NOT DISTRIBUTE.\n\n";
  259. #  endif
  260. #endif
  261.  
  262. #ifdef SFX
  263. #  ifdef VMSCLI
  264.    /* UnzipSFXBanner[] is also used in vms/cmdline.c:  do not make it static */
  265.      char Far UnzipSFXBanner[] =
  266. #  else
  267.      static char Far UnzipSFXBanner[] =
  268. #  endif
  269.      "UnZipSFX %d.%d%d%s of %s, by Info-ZIP (Zip-Bugs@lists.wku.edu).\n";
  270. #  ifdef SFX_EXDIR
  271.      static char Far UnzipSFXOpts[] =
  272.     "Valid options are -tfupcz and -d <exdir>; modifiers are -abjnoqCL%sV%s.\n";
  273. #  else
  274.      static char Far UnzipSFXOpts[] =
  275.        "Valid options are -tfupcz; modifiers are -abjnoqCL%sV%s.\n";
  276. #  endif
  277. #else /* !SFX */
  278.    static char Far CompileOptions[] = "UnZip special compilation options:\n";
  279.    static char Far CompileOptFormat[] = "\t%s\n";
  280.    static char Far EnvOptions[] = "\nUnZip and ZipInfo environment options:\n";
  281.    static char Far EnvOptFormat[] = "%16s:  %s\n";
  282.    static char Far None[] = "[none]";
  283. #  ifdef ASM_CRC
  284.      static char Far AsmCRC[] = "ASM_CRC";
  285. #  endif
  286. #  ifdef ASM_INFLATECODES
  287.      static char Far AsmInflateCodes[] = "ASM_INFLATECODES";
  288. #  endif
  289. #  ifdef CHECK_VERSIONS
  290.      static char Far Check_Versions[] = "CHECK_VERSIONS";
  291. #  endif
  292. #  ifdef COPYRIGHT_CLEAN
  293.      static char Far Copyright_Clean[] =
  294.      "COPYRIGHT_CLEAN (PKZIP 0.9x unreducing method not supported)";
  295. #  endif
  296. #  ifdef DEBUG
  297.      static char Far UDebug[] = "DEBUG";
  298. #  endif
  299. #  ifdef DEBUG_TIME
  300.      static char Far DebugTime[] = "DEBUG_TIME";
  301. #  endif
  302. #  ifdef DLL
  303.      static char Far Dll[] = "DLL";
  304. #  endif
  305. #  ifdef DOSWILD
  306.      static char Far DosWild[] = "DOSWILD";
  307. #  endif
  308. #  ifdef LZW_CLEAN
  309.      static char Far LZW_Clean[] =
  310.      "LZW_CLEAN (PKZIP/Zip 1.x unshrinking method not supported)";
  311. #  endif
  312. #  ifndef MORE
  313.      static char Far No_More[] = "NO_MORE";
  314. #  endif
  315. #  ifdef NO_ZIPINFO
  316.      static char Far No_ZipInfo[] = "NO_ZIPINFO";
  317. #  endif
  318. #  ifdef NTSD_EAS
  319.      static char Far NTSDExtAttrib[] = "NTSD_EAS";
  320. #  endif
  321. #  ifdef OS2_EAS
  322.      static char Far OS2ExtAttrib[] = "OS2_EAS";
  323. #  endif
  324. #  ifdef REENTRANT
  325.      static char Far Reentrant[] = "REENTRANT";
  326. #  endif
  327. #  ifdef REGARGS
  328.      static char Far RegArgs[] = "REGARGS";
  329. #  endif
  330. #  ifdef RETURN_CODES
  331.      static char Far Return_Codes[] = "RETURN_CODES";
  332. #  endif
  333. #  ifdef TIMESTAMP
  334.      static char Far TimeStamp[] = "TIMESTAMP";
  335. #  endif
  336. #  ifdef UNIXBACKUP
  337.      static char Far UnixBackup[] = "UNIXBACKUP";
  338. #  endif
  339. #  ifdef USE_EF_UT_TIME
  340.      static char Far Use_EF_UT_time[] = "USE_EF_UT_TIME";
  341. #  endif
  342. #  ifndef LZW_CLEAN
  343.      static char Far Use_Unshrink[] =
  344.      "USE_UNSHRINK (PKZIP/Zip 1.x unshrinking method supported)";
  345. #  endif
  346. #  ifndef COPYRIGHT_CLEAN
  347.      static char Far Use_Smith_Code[] =
  348.      "USE_SMITH_CODE (PKZIP 0.9x unreducing method supported)";
  349. #  endif
  350. #  ifdef USE_VFAT
  351.      static char Far Use_VFAT_support[] = "USE_VFAT";
  352. #  endif
  353. #  ifdef USE_ZLIB
  354.      static char Far UseZlib[] =
  355.      "USE_ZLIB (compiled with version %s; using version %s)";
  356. #  endif
  357. #  ifdef VMS_TEXT_CONV
  358.      static char Far VmsTextConv[] = "VMS_TEXT_CONV";
  359. #  endif
  360. #  ifdef VMSCLI
  361.      static char Far VmsCLI[] = "VMSCLI";
  362. #  endif
  363. #  ifdef VMSWILD
  364.      static char Far VmsWild[] = "VMSWILD";
  365. #  endif
  366. #  if CRYPT
  367. #    ifdef PASSWD_FROM_STDIN
  368.        static char Far PasswdStdin[] = "PASSWD_FROM_STDIN";
  369. #    endif
  370.      static char Far Decryption[] = "\t[decryption, version %d.%d%s of %s]\n";
  371.      static char Far CryptDate[] = CR_VERSION_DATE;
  372. #  endif
  373. #  ifndef __RSXNT__
  374. #    ifdef __EMX__
  375.        static char Far EnvEMX[] = "EMX";
  376.        static char Far EnvEMXOPT[] = "EMXOPT";
  377. #    endif
  378. #    ifdef __GO32__
  379.        static char Far EnvGO32[] = "GO32";
  380.        static char Far EnvGO32TMP[] = "GO32TMP";
  381. #    endif
  382. #  endif /* !__RSXNT__ */
  383.  
  384. #ifdef VMS
  385. /* UnzipUsageLine1[] is also used in vms/cmdline.c:  do not make it static */
  386.    char Far UnzipUsageLine1[] = "\
  387. UnZip %d.%d%d%s of %s, by Info-ZIP.  For more details see: unzip -v.\n\n";
  388. #ifdef COPYRIGHT_CLEAN
  389.    static char Far UnzipUsageLine1v[] = "\
  390. UnZip %d.%d%d%s of %s, by Info-ZIP.  Maintained by Greg Roelofs.  Send\n\
  391. bug reports to the authors at Zip-Bugs@lists.wku.edu; see README for details.\
  392. \n\n";
  393. #else
  394.    static char Far UnzipUsageLine1v[] = "\
  395. UnZip %d.%d%d%s of %s, by Info-ZIP.  UnReduce (c) 1989 by S. H. Smith.\n\
  396. Send bug reports to authors at Zip-Bugs@lists.wku.edu; see README for details.\
  397. \n\n";
  398. #endif /* ?COPYRIGHT_CLEAN */
  399. #else /* !VMS */
  400. #ifdef COPYRIGHT_CLEAN
  401.    static char Far UnzipUsageLine1[] = "\
  402. UnZip %d.%d%d%s of %s, by Info-ZIP.  Maintained by Greg Roelofs.  Send\n\
  403. bug reports to the authors at Zip-Bugs@lists.wku.edu; see README for details.\
  404. \n\n";
  405. #else
  406.    static char Far UnzipUsageLine1[] = "\
  407. UnZip %d.%d%d%s of %s, by Info-ZIP.  UnReduce (c) 1989 by S. H. Smith.\n\
  408. Send bug reports to authors at Zip-Bugs@lists.wku.edu; see README for details.\
  409. \n\n";
  410. #endif /* ?COPYRIGHT_CLEAN */
  411. #define UnzipUsageLine1v        UnzipUsageLine1
  412. #endif /* ?VMS */
  413.  
  414. /*
  415. static char Far UnzipUsageLine2v[] = "\
  416. Latest sources and executables are always in ftp.uu.net:/pub/archiving/zip, at\
  417. \nleast as of date of this release; see \"Where\" for other ftp and non-ftp \
  418. sites.\n\n";
  419.  */
  420. static char Far UnzipUsageLine2v[] = "\
  421. Latest sources and executables are at ftp://ftp.cdrom.com/pub/infozip/ , as of\
  422. \nabove date; see http://www.cdrom.com/pub/infozip/UnZip.html for other sites.\
  423. \n\n";
  424.  
  425. static char Far UnzipUsageLine2[] = "\
  426. Usage: unzip %s[-opts[modifiers]] file[.zip] [list] [-x xlist] [-d exdir]\n \
  427.  Default action is to extract files in list, except those in xlist, to exdir;\n\
  428.   file[.zip] may be a wildcard.  %s\n";
  429.  
  430. #ifdef NO_ZIPINFO
  431. #  define ZIPINFO_MODE_OPTION  ""
  432.    static char Far ZipInfoMode[] =
  433.      "(ZipInfo mode is disabled in this version.)";
  434. #else
  435. #  define ZIPINFO_MODE_OPTION  "[-Z] "
  436. #  ifdef VMS
  437.      static char Far ZipInfoMode[] =
  438.        "\"-Z\" => ZipInfo mode (`unzip \"-Z\"' for usage).";
  439. #  else
  440.      static char Far ZipInfoMode[] =
  441.        "-Z => ZipInfo mode (\"unzip -Z\" for usage).";
  442. #  endif
  443. #endif /* ?NO_ZIPINFO */
  444.  
  445. #ifdef VMS
  446.    static char Far VMSusageLine2b[] = "\
  447. => define foreign command symbol in LOGIN.COM:  $ unzip :== $dev:[dir]unzip.exe\
  448. \n";
  449. #endif
  450.  
  451. static char Far UnzipUsageLine3[] = "\n\
  452.   -p  extract files to pipe, no messages     -l  list files (short format)\n\
  453.   -f  freshen existing files, create none    -t  test compressed archive data\n\
  454.   -u  update files, create if necessary      -z  display archive comment\n\
  455.   -x  exclude files that follow (in xlist)   -d  extract files into exdir\n\
  456. %s\n";
  457.  
  458. static char Far UnzipUsageLine4[] = "\
  459. modifiers:                                   -q  quiet mode (-qq => quieter)\n\
  460.   -n  never overwrite existing files         -a  auto-convert any text files\n\
  461.   -o  overwrite files WITHOUT prompting      -aa treat ALL files as text\n \
  462.  -j  junk paths (don't make directories)    -v  be verbose/print version info\n\
  463.  %c-C%c match filenames case-insensitively    %c-L%c make (some) names \
  464. lowercase\n %-42s %c-V%c retain VMS version numbers\n%s";
  465.  
  466. static char Far UnzipUsageLine5[] = "\
  467. Examples (see unzip.doc for more info):\n\
  468.   unzip data1 -x joe   => extract all files except joe from zipfile data1.zip\n\
  469. %s\
  470.   unzip -fo foo %-6s => quietly replace existing %s if archive file newer\n";
  471. #endif /* ?SFX */
  472.  
  473.  
  474.  
  475.  
  476.  
  477. /*****************************/
  478. /*  main() / UzpMain() stub  */
  479. /*****************************/
  480.  
  481. int MAIN(argc, argv)   /* return PK-type error code (except under VMS) */
  482.     int argc;
  483.     char *argv[];
  484. {
  485.     int r;
  486.  
  487.     CONSTRUCTGLOBALS();
  488.     r = unzip(__G__ argc, argv);
  489.     DESTROYGLOBALS()
  490.     RETURN(r);
  491. }
  492.  
  493.  
  494.  
  495.  
  496. /*******************************/
  497. /*  Primary UnZip entry point  */
  498. /*******************************/
  499.  
  500. int unzip(__G__ argc, argv)
  501.     __GDEF
  502.     int argc;
  503.     char *argv[];
  504. {
  505. #ifndef NO_ZIPINFO
  506.     char *p;
  507. #endif
  508. #ifdef DOS_H68_OS2_W32
  509.     int i;
  510. #endif
  511.     int retcode, error=FALSE;
  512.  
  513. /*---------------------------------------------------------------------------
  514.     Macintosh initialization code.
  515.   ---------------------------------------------------------------------------*/
  516.  
  517. #ifdef MACOS
  518.     int a;
  519.  
  520.     for (a = 0;  a < 4;  ++a)
  521.         G.rghCursor[a] = GetCursor(a+128);
  522.     G.giCursor = 0;
  523.     error = FALSE;
  524. #endif
  525.  
  526. #if defined(__IBMC__) && defined(__DEBUG_ALLOC__)
  527.     extern void DebugMalloc(void);
  528.  
  529.     atexit(DebugMalloc);
  530. #endif
  531.  
  532. #ifdef MALLOC_WORK
  533.     G.area.Slide =(uch *)calloc(8193, sizeof(short)+sizeof(char)+sizeof(char));
  534.     G.area.shrink.Parent = (shrint *)G.area.Slide;
  535.     G.area.shrink.value = G.area.Slide + (sizeof(shrint)*(HSIZE+1));
  536.     G.area.shrink.Stack = G.area.Slide +
  537.                            (sizeof(shrint) + sizeof(uch))*(HSIZE+1);
  538. #endif
  539.  
  540. /*---------------------------------------------------------------------------
  541.     Human68K initialization code.
  542.   ---------------------------------------------------------------------------*/
  543.  
  544. #ifdef __human68k__
  545.     InitTwentyOne();
  546. #endif
  547.  
  548. /*---------------------------------------------------------------------------
  549.     Acorn RISC OS initialization code.
  550.   ---------------------------------------------------------------------------*/
  551.  
  552. #ifdef RISCOS
  553.     set_prefix();
  554. #endif
  555.  
  556. /*---------------------------------------------------------------------------
  557.     Set signal handler for restoring echo, warn of zipfile corruption, etc.
  558.   ---------------------------------------------------------------------------*/
  559.  
  560. #if (!defined(CMS_MVS))
  561.     signal(SIGINT, handler);
  562. #ifdef SIGTERM                 /* some systems really have no SIGTERM */
  563.     signal(SIGTERM, handler);
  564. #endif
  565. #ifdef SIGBUS
  566.     signal(SIGBUS, handler);
  567. #endif
  568. #ifdef SIGSEGV
  569.     signal(SIGSEGV, handler);
  570. #endif
  571. #endif /* !CMS_MVS */
  572.  
  573. #if (defined(WIN32) && defined(__RSXNT__))
  574.     for (i = 0 ; i < argc; i++) {
  575.        _ISO_INTERN(argv[i]);
  576.     }
  577. #endif
  578.  
  579. /*---------------------------------------------------------------------------
  580.     First figure out if we're running in UnZip mode or ZipInfo mode, and put
  581.     the appropriate environment-variable options into the queue.  Then rip
  582.     through any command-line options lurking about...
  583.   ---------------------------------------------------------------------------*/
  584.  
  585. #ifdef SFX
  586.     G.argv0 = argv[0];
  587. #if defined(OS2) || defined(WIN32)
  588.     G.zipfn = GetLoadPath(__G);/* non-MSC NT puts path into G.filename[] */
  589. #else
  590.     G.zipfn = G.argv0;
  591. #endif
  592.  
  593. #ifdef VMSCLI
  594.     {
  595.         ulg status = vms_unzip_cmdline(&argc, &argv);
  596.         if (!(status & 1))
  597.             return status;
  598.     }
  599. #endif /* VMSCLI */
  600.  
  601.     G.zipinfo_mode = FALSE;
  602.     error = uz_opts(__G__ &argc, &argv);   /* UnZipSFX call only */
  603.  
  604. #else /* !SFX */
  605.  
  606.     G.noargs = (argc == 1);   /* no options, no zipfile, no anything */
  607.  
  608. #ifdef RISCOS
  609.     /* get the extensions to swap from environment */
  610.     getRISCOSexts(ENV_UNZIPEXTS);
  611. #endif
  612.  
  613. #ifdef MSDOS
  614.     /* extract MKS extended argument list from environment (before envargs!) */
  615.     mksargs(&argc, &argv);
  616. #endif
  617.  
  618. #ifdef VMSCLI
  619.     {
  620.         ulg status = vms_unzip_cmdline(&argc, &argv);
  621.         if (!(status & 1))
  622.             return status;
  623.     }
  624. #endif /* VMSCLI */
  625.  
  626. #ifndef NO_ZIPINFO
  627.     if ((p = strrchr(argv[0], DIR_END)) == (char *)NULL)
  628.         p = argv[0];
  629.     else
  630.         ++p;
  631.  
  632.     if (STRNICMP(p, LoadFarStringSmall(Zipnfo), 7) == 0 ||
  633.         STRNICMP(p, "ii", 2) == 0 ||
  634.         (argc > 1 && strncmp(argv[1], "-Z", 2) == 0))
  635.     {
  636.         G.zipinfo_mode = TRUE;
  637.         envargs(__G__ &argc, &argv, LoadFarStringSmall(EnvZipInfo),
  638.           LoadFarStringSmall2(EnvZipInfo2));
  639.         error = zi_opts(__G__ &argc, &argv);
  640.     } else
  641. #endif /* NO_ZIPINFO */
  642.     {
  643.         G.zipinfo_mode = FALSE;
  644.         envargs(__G__ &argc, &argv, LoadFarStringSmall(EnvUnZip),
  645.           LoadFarStringSmall2(EnvUnZip2));
  646.         error = uz_opts(__G__ &argc, &argv);
  647.     }
  648.  
  649. #endif /* ?SFX */
  650.  
  651.     if ((argc < 0) || error)
  652.         return error;
  653.  
  654. /*---------------------------------------------------------------------------
  655.     Now get the zipfile name from the command line and then process any re-
  656.     maining options and file specifications.
  657.   ---------------------------------------------------------------------------*/
  658.  
  659. #ifdef DOS_H68_OS2_W32
  660.     /* convert MSDOS-style directory separators to Unix-style ones for
  661.      * user's convenience (include zipfile name itself)
  662.      */
  663.     for (G.pfnames = argv, i = argc+1;  i > 0;  --i) {
  664.         char *q;
  665.  
  666.         for (q = *G.pfnames;  *q;  ++q)
  667.             if (*q == '\\')
  668.                 *q = '/';
  669.         ++G.pfnames;
  670.     }
  671. #endif /* DOS_H68_OS2_W32 */
  672.  
  673. #ifndef SFX
  674.     G.wildzipfn = *argv++;
  675. #endif
  676.  
  677. #if (defined(SFX) && !defined(SFX_EXDIR)) /* only check for -x */
  678.  
  679.     G.filespecs = argc;
  680.     G.xfilespecs = 0;
  681.  
  682.     if (argc > 0) {
  683.         char **pp = argv-1;
  684.  
  685.         G.pfnames = argv;
  686.         while (*++pp)
  687.             if (strcmp(*pp, "-x") == 0) {
  688.                 if (pp > argv) {
  689.                     *pp = 0;              /* terminate G.pfnames */
  690.                     G.filespecs = pp - G.pfnames;
  691.                 } else {
  692.                     G.pfnames = fnames;  /* defaults */
  693.                     G.filespecs = 0;
  694.                 }
  695.                 G.pxnames = pp + 1;      /* excluded-names ptr: _after_ -x */
  696.                 G.xfilespecs = argc - G.filespecs - 1;
  697.                 break;                    /* skip rest of args */
  698.             }
  699.         G.process_all_files = FALSE;
  700.     } else
  701.         G.process_all_files = TRUE;      /* for speed */
  702.  
  703. #else /* !SFX || SFX_EXDIR */             /* check for -x or -d */
  704.  
  705.     G.filespecs = argc;
  706.     G.xfilespecs = 0;
  707.  
  708.     if (argc > 0) {
  709.         int in_files=FALSE, in_xfiles=FALSE;
  710.         char **pp = argv-1;
  711.  
  712.         G.process_all_files = FALSE;
  713.         G.pfnames = argv;
  714.         while (*++pp) {
  715.             Trace((stderr, "pp - argv = %d\n", pp-argv));
  716. #ifdef CMS_MVS
  717.             if (!G.dflag && STRNICMP(*pp, "-d", 2) == 0) {
  718. #else
  719.             if (!G.dflag && strncmp(*pp, "-d", 2) == 0) {
  720. #endif
  721.                 char *q = *pp;
  722.                 int firstarg = (pp == argv);
  723.  
  724.                 G.dflag = TRUE;
  725.                 if (in_files) {      /* ... zipfile ... -d exdir ... */
  726.                     *pp = (char *)NULL;         /* terminate G.pfnames */
  727.                     G.filespecs = pp - G.pfnames;
  728.                     in_files = FALSE;
  729.                 } else if (in_xfiles) {
  730.                     *pp = (char *)NULL;         /* terminate G.pxnames */
  731.                     G.xfilespecs = pp - G.pxnames;
  732.                     /* "... -x xlist -d exdir":  nothing left */
  733.                 }
  734.                 /* first check for "-dexdir", then for "-d exdir" */
  735.                 if (q[2])
  736.                     q += 2;
  737.                 else if (*++pp)
  738.                     q = *pp;
  739.                 else {
  740.                     Info(slide, 0x401, ((char *)slide,
  741.                       LoadFarString(MustGiveExdir)));
  742.                     return(PK_PARAM);  /* don't extract here by accident */
  743.                 }
  744.                 if (G.extract_flag) {
  745.                     G.create_dirs = !G.fflag;
  746.                     if ((error = checkdir(__G__ q, ROOT)) > 2) {
  747.                         return(error);  /* out of memory, or file in way */
  748.                     }
  749.                 } else
  750.                     Info(slide, 0x401, ((char *)slide,
  751.                       LoadFarString(NotExtracting)));
  752.                 if (firstarg)   /* ... zipfile -d exdir ... */
  753.                     if (pp[1]) {
  754.                         G.pfnames = pp + 1;  /* argv+2 */
  755.                         G.filespecs = argc - (G.pfnames-argv);  /* for now... */
  756.                     } else {
  757.                         G.process_all_files = TRUE;
  758.                         G.pfnames = fnames;  /* GRR: necessary? */
  759.                         G.filespecs = 0;     /* GRR: necessary? */
  760.                         break;
  761.                     }
  762.             } else if (!in_xfiles) {
  763.                 if (strcmp(*pp, "-x") == 0) {
  764.                     in_xfiles = TRUE;
  765.                     if (pp == G.pfnames) {
  766.                         G.pfnames = fnames;  /* defaults */
  767.                         G.filespecs = 0;
  768.                     } else if (in_files) {
  769.                         *pp = 0;                   /* terminate G.pfnames */
  770.                         G.filespecs = pp - G.pfnames;  /* adjust count */
  771.                         in_files = FALSE;
  772.                     }
  773.                     G.pxnames = pp + 1; /* excluded-names ptr starts after -x */
  774.                     G.xfilespecs = argc - (G.pxnames-argv);  /* anything left */
  775.                 } else
  776.                     in_files = TRUE;
  777.             }
  778.         }
  779.     } else
  780.         G.process_all_files = TRUE;      /* for speed */
  781.  
  782. #endif /* ?(SFX && !SFX_EXDIR) */
  783.  
  784. /*---------------------------------------------------------------------------
  785.     Okey dokey, we have everything we need to get started.  Let's roll.
  786.   ---------------------------------------------------------------------------*/
  787.  
  788.     retcode = process_zipfiles(__G);
  789.     return(retcode);
  790.  
  791. } /* end main()/unzip() */
  792.  
  793.  
  794.  
  795.  
  796.  
  797. /**********************/
  798. /* Function uz_opts() */
  799. /**********************/
  800.  
  801. int uz_opts(__G__ pargc, pargv)
  802.     int *pargc;
  803.     char ***pargv;
  804.     __GDEF
  805. {
  806.     char **argv, *s;
  807. #if (!defined(SFX) || defined(SFX_EXDIR))
  808.     char *exdir = NULL;   /* initialized to shut up false GCC warning */
  809. #endif
  810.     int argc, c, error=FALSE, negative=0;
  811.  
  812.  
  813.     argc = *pargc;
  814.     argv = *pargv;
  815.  
  816.     while (--argc > 0 && (*++argv)[0] == '-') {
  817.         s = argv[0] + 1;
  818.         while ((c = *s++) != 0) {    /* "!= 0":  prevent Turbo C warning */
  819. #ifdef CMS_MVS
  820.             switch (tolower(c))
  821. #else
  822.             switch (c)
  823. #endif
  824.             {
  825.                 case ('-'):
  826.                     ++negative;
  827.                     break;
  828.                 case ('a'):
  829.                     if (negative) {
  830.                         G.aflag = MAX(G.aflag-negative,0);
  831.                         negative = 0;
  832.                     } else
  833.                         ++G.aflag;
  834.                     break;
  835. #if (defined(DLL) && defined(API_DOC))
  836.                 case ('A'):    /* extended help for API */
  837.                     APIhelp(__G__ argc,argv);
  838.                     *pargc = -1;  /* signal to exit successfully */
  839.                     return 0;
  840. #endif
  841.                 case ('b'):
  842.                     if (negative) {
  843. #ifdef VMS
  844.                         G.bflag = MAX(G.bflag-negative,0);
  845. #endif
  846.                         negative = 0;   /* do nothing:  "-b" is default */
  847.                     } else {
  848. #ifdef VMS
  849.                         if (G.aflag == 0)
  850.                            ++G.bflag;
  851. #endif
  852.                         G.aflag = 0;
  853.                     }
  854.                     break;
  855. #ifdef UNIXBACKUP
  856.                 case ('B'): /* -B: back up existing files */
  857.                     if (negative)
  858.                         G.B_flag = FALSE, negative = 0;
  859.                     else
  860.                         G.B_flag = TRUE;
  861.                     break;
  862. #endif
  863.                 case ('c'):
  864.                     if (negative) {
  865.                         G.cflag = FALSE, negative = 0;
  866. #ifdef NATIVE
  867.                         G.aflag = 0;
  868. #endif
  869.                     } else {
  870.                         G.cflag = TRUE;
  871. #ifdef NATIVE
  872.                         G.aflag = 2;  /* so you can read it on the screen */
  873. #endif
  874. #ifdef DLL
  875.                         if (G.redirect_text)
  876.                             G.redirect_data = 2;
  877. #endif
  878.                     }
  879.                     break;
  880. #ifndef CMS_MVS
  881.                 case ('C'):    /* -C:  match filenames case-insensitively */
  882.                     if (negative)
  883.                         G.C_flag = FALSE, negative = 0;
  884.                     else
  885.                         G.C_flag = TRUE;
  886.                     break;
  887. #endif /* !CMS_MVS */
  888. #if (!defined(SFX) || defined(SFX_EXDIR))
  889.                 case ('d'):
  890.                     if (negative) {   /* negative not allowed with -d exdir */
  891.                         Info(slide, 0x401, ((char *)slide,
  892.                           LoadFarString(MustGiveExdir)));
  893.                         return(PK_PARAM);  /* don't extract here by accident */
  894.                     }
  895.                     if (G.dflag) {
  896.                         Info(slide, 0x401, ((char *)slide,
  897.                           LoadFarString(OnlyOneExdir)));
  898.                         return(PK_PARAM);    /* GRR:  stupid restriction? */
  899.                     } else {
  900.                         G.dflag = TRUE;
  901.                         /* first check for "-dexdir", then for "-d exdir" */
  902.                         exdir = s;
  903.                         if (*exdir == 0) {
  904.                             if (argc > 1) {
  905.                                 --argc;
  906.                                 exdir = *++argv;
  907.                                 if (*exdir == '-') {
  908.                                     Info(slide, 0x401, ((char *)slide,
  909.                                       LoadFarString(MustGiveExdir)));
  910.                                     return(PK_PARAM);
  911.                                 }
  912.                                 /* else exdir points at extraction dir */
  913.                             } else {
  914.                                 Info(slide, 0x401, ((char *)slide,
  915.                                   LoadFarString(MustGiveExdir)));
  916.                                 return(PK_PARAM);
  917.                             }
  918.                         }
  919.                         /* exdir now points at extraction dir (-dexdir or
  920.                          *  -d exdir); point s at end of exdir to avoid mis-
  921.                          *  interpretation of exdir characters as more options
  922.                          */
  923.                         if (*s != 0)
  924.                             while (*++s != 0)
  925.                                 ;
  926.                     }
  927.                     break;
  928. #endif /* !SFX || SFX_EXDIR */
  929.                 case ('e'):    /* just ignore -e, -x options (extract) */
  930.                     break;
  931.                 case ('f'):    /* "freshen" (extract only newer files) */
  932.                     if (negative)
  933.                         G.fflag = G.uflag = FALSE, negative = 0;
  934.                     else
  935.                         G.fflag = G.uflag = TRUE;
  936.                     break;
  937.                 case ('h'):    /* just print help message and quit */
  938.                     *pargc = -1;
  939.                     return USAGE(PK_OK);
  940.                 case ('j'):    /* junk pathnames/directory structure */
  941.                     if (negative)
  942.                         G.jflag = FALSE, negative = 0;
  943.                     else
  944.                         G.jflag = TRUE;
  945.                     break;
  946. #ifndef SFX
  947.                 case ('l'):
  948.                     if (negative) {
  949.                         G.vflag = MAX(G.vflag-negative,0);
  950.                         negative = 0;
  951.                     } else
  952.                         ++G.vflag;
  953.                     break;
  954. #endif /* !SFX */
  955. #ifndef CMS_MVS
  956.                 case ('L'):    /* convert (some) filenames to lowercase */
  957.                     if (negative)
  958.                         G.L_flag = FALSE, negative = 0;
  959.                     else
  960.                         G.L_flag = TRUE;
  961.                     break;
  962. #endif /* !CMS_MVS */
  963. #ifdef MORE
  964. #ifdef CMS_MVS
  965.                 case ('m'):
  966. #endif
  967.                 case ('M'):    /* send all screen output through "more" fn. */
  968. /* GRR:  eventually check for numerical argument => height */
  969.                     if (negative)
  970.                         G.M_flag = FALSE, negative = 0;
  971.                     else
  972.                         G.M_flag = TRUE;
  973.                     break;
  974. #endif /* MORE */
  975.                 case ('n'):    /* don't overwrite any files */
  976.                     if (negative)
  977.                         G.overwrite_none = FALSE, negative = 0;
  978.                     else
  979.                         G.overwrite_none = TRUE;
  980.                     break;
  981. #ifdef AMIGA
  982.                 case ('N'):    /* restore comments as filenotes */
  983.                     if (negative)
  984.                         G.N_flag = FALSE, negative = 0;
  985.                     else
  986.                         G.N_flag = TRUE;
  987.                     break;
  988. #endif /* AMIGA */
  989.                 case ('o'):    /* OK to overwrite files without prompting */
  990.                     if (negative) {
  991.                         G.overwrite_all = MAX(G.overwrite_all-negative,0);
  992.                         negative = 0;
  993.                     } else
  994.                         ++G.overwrite_all;
  995.                     break;
  996.                 case ('p'):    /* pipes:  extract to stdout, no messages */
  997.                     if (negative) {
  998.                         G.cflag = FALSE;
  999.                         G.qflag = MAX(G.qflag-999,0);
  1000.                         negative = 0;
  1001.                     } else {
  1002.                         G.cflag = TRUE;
  1003.                         G.qflag += 999;
  1004.                     }
  1005.                     break;
  1006. #if CRYPT
  1007.                 /* GRR:  yes, this is highly insecure, but dozens of people
  1008.                  * have pestered us for this, so here we go... */
  1009.                 case ('P'):
  1010.                     if (negative) {   /* negative not allowed with -P passwd */
  1011.                         Info(slide, 0x401, ((char *)slide,
  1012.                           LoadFarString(MustGivePasswd)));
  1013.                         return(PK_PARAM);  /* don't extract here by accident */
  1014.                     }
  1015.                     if (G.P_flag) {
  1016. /*
  1017.                         GRR:  eventually support multiple passwords?
  1018.                         Info(slide, 0x401, ((char *)slide,
  1019.                           LoadFarString(OnlyOnePasswd)));
  1020.                         return(PK_PARAM);
  1021.  */
  1022.                     } else {
  1023.                         G.P_flag = TRUE;
  1024.                         /* first check for "-dpasswd", then for "-d passwd" */
  1025.                         G.pwdarg = s;
  1026.                         if (*G.pwdarg == 0) {
  1027.                             if (argc > 1) {
  1028.                                 --argc;
  1029.                                 G.pwdarg = *++argv;
  1030.                                 if (*G.pwdarg == '-') {
  1031.                                     Info(slide, 0x401, ((char *)slide,
  1032.                                       LoadFarString(MustGivePasswd)));
  1033.                                     return(PK_PARAM);
  1034.                                 }
  1035.                                 /* else pwdarg points at decryption password */
  1036.                             } else {
  1037.                                 Info(slide, 0x401, ((char *)slide,
  1038.                                   LoadFarString(MustGivePasswd)));
  1039.                                 return(PK_PARAM);
  1040.                             }
  1041.                         }
  1042.                         /* pwdarg now points at decryption password (-Ppasswd or
  1043.                          *  -P passwd); point s at end of passwd to avoid mis-
  1044.                          *  interpretation of passwd characters as more options
  1045.                          */
  1046.                         if (*s != 0)
  1047.                             while (*++s != 0)
  1048.                                 ;
  1049.                     }
  1050.                     break;
  1051. #endif /* CRYPT */
  1052.                 case ('q'):    /* quiet:  fewer comments/messages */
  1053.                     if (negative) {
  1054.                         G.qflag = MAX(G.qflag-negative,0);
  1055.                         negative = 0;
  1056.                     } else
  1057.                         ++G.qflag;
  1058.                     break;
  1059. #ifdef QDOS
  1060.                 case ('Q'):   /* QDOS flags */
  1061.                     qlflag ^= strtol(s, &s, 10);
  1062.                     break;    /* we XOR this as we can config qlflags */
  1063. #endif
  1064. #ifdef DOS_OS2_W32
  1065.                 case ('s'):    /* spaces in filenames:  allow by default */
  1066.                     if (negative)
  1067.                         G.sflag = FALSE, negative = 0;
  1068.                     else
  1069.                         G.sflag = TRUE;
  1070.                     break;
  1071. #endif /* DOS_OS2_W32 */
  1072.                 case ('t'):
  1073.                     if (negative)
  1074.                         G.tflag = FALSE, negative = 0;
  1075.                     else
  1076.                         G.tflag = TRUE;
  1077.                     break;
  1078. #ifdef TIMESTAMP
  1079.                 case ('T'):
  1080.                     if (negative)
  1081.                         G.T_flag = FALSE, negative = 0;
  1082.                     else
  1083.                         G.T_flag = TRUE;
  1084.                     break;
  1085. #endif
  1086.                 case ('u'):    /* update (extract only new and newer files) */
  1087.                     if (negative)
  1088.                         G.uflag = FALSE, negative = 0;
  1089.                     else
  1090.                         G.uflag = TRUE;
  1091.                     break;
  1092. #ifndef CMS_MVS
  1093.                 case ('U'):    /* obsolete; to be removed in version 6.0 */
  1094.                     if (negative)
  1095.                         G.L_flag = TRUE, negative = 0;
  1096.                     else
  1097.                         G.L_flag = FALSE;
  1098.                     break;
  1099. #endif /* !CMS_MVS */
  1100. #ifndef SFX
  1101.                 case ('v'):    /* verbose */
  1102.                     if (negative) {
  1103.                         G.vflag = MAX(G.vflag-negative,0);
  1104.                         negative = 0;
  1105.                     } else if (G.vflag)
  1106.                         ++G.vflag;
  1107.                     else
  1108.                         G.vflag = 2;
  1109.                     break;
  1110. #endif /* !SFX */
  1111. #ifndef CMS_MVS
  1112.                 case ('V'):    /* Version (retain VMS/DEC-20 file versions) */
  1113.                     if (negative)
  1114.                         G.V_flag = FALSE, negative = 0;
  1115.                     else
  1116.                         G.V_flag = TRUE;
  1117.                     break;
  1118. #endif /* !CMS_MVS */
  1119.                 case ('x'):    /* extract:  default */
  1120. #ifdef SFX
  1121.                     /* when 'x' is the only option in this argument, and the
  1122.                      * next arg is not an option, assume this initiates an
  1123.                      * exclusion list (-x xlist):  terminate option-scanning
  1124.                      * and leave uz_opts with argv still pointing to "-x";
  1125.                      * the xlist is processed later
  1126.                      */
  1127.                     if (s - argv[0] == 2 && *s == 0 &&
  1128.                         argc > 1 && argv[1][0] != '-') {
  1129.                         /* break out of nested loops without "++argv;--argc" */
  1130.                         goto opts_done;
  1131.                     }
  1132. #endif /* SFX */
  1133.                     break;
  1134. #if defined(VMS) || defined(UNIX) || defined(OS2) || defined(WIN32)
  1135.                 case ('X'):   /* restore owner/protection info (need privs?) */
  1136.                     if (negative) {
  1137.                         G.X_flag = MAX(G.X_flag-negative,0);
  1138.                         negative = 0;
  1139.                     } else
  1140.                         ++G.X_flag;
  1141.                     break;
  1142. #endif /* VMS || UNIX || OS2 || WIN32 */
  1143.                 case ('z'):    /* display only the archive comment */
  1144.                     if (negative) {
  1145.                         G.zflag = MAX(G.zflag-negative,0);
  1146.                         negative = 0;
  1147.                     } else
  1148.                         ++G.zflag;
  1149.                     break;
  1150. #ifndef SFX
  1151.                 case ('Z'):    /* should have been first option (ZipInfo) */
  1152.                     Info(slide, 0x401, ((char *)slide, LoadFarString(Zfirst)));
  1153.                     error = TRUE;
  1154.                     break;
  1155. #endif /* !SFX */
  1156. #ifdef DOS_OS2_W32
  1157.                 case ('$'):
  1158.                     if (negative) {
  1159.                         G.volflag = MAX(G.volflag-negative,0);
  1160.                         negative = 0;
  1161.                     } else
  1162.                         ++G.volflag;
  1163.                     break;
  1164. #endif /* DOS_OS2_W32 */
  1165.                 default:
  1166.                     error = TRUE;
  1167.                     break;
  1168.  
  1169.             } /* end switch */
  1170.         } /* end while (not end of argument string) */
  1171.     } /* end while (not done with switches) */
  1172.  
  1173. /*---------------------------------------------------------------------------
  1174.     Check for nonsensical combinations of options.
  1175.   ---------------------------------------------------------------------------*/
  1176.  
  1177. #ifdef SFX
  1178. opts_done:  /* yes, very ugly...but only used by UnZipSFX with -x xlist */
  1179. #endif
  1180.  
  1181.     if ((G.cflag && G.tflag) || (G.cflag && G.uflag) ||
  1182.         (G.tflag && G.uflag) || (G.fflag && G.overwrite_none))
  1183.     {
  1184.         Info(slide, 0x401, ((char *)slide, LoadFarString(InvalidOptionsMsg)));
  1185.         error = TRUE;
  1186.     }
  1187.     if (G.aflag > 2)
  1188.         G.aflag = 2;
  1189. #ifdef VMS
  1190.     if (G.bflag > 2)
  1191.         G.bflag = 2;
  1192. #endif
  1193.     if (G.overwrite_all && G.overwrite_none) {
  1194.         Info(slide, 0x401, ((char *)slide, LoadFarString(IgnoreOOptionMsg)));
  1195.         G.overwrite_all = FALSE;
  1196.     }
  1197. #ifdef MORE
  1198.     if (G.M_flag && !isatty(1))  /* stdout redirected: "more" func. useless */
  1199.         G.M_flag = 0;
  1200. #endif
  1201.  
  1202. #ifdef SFX
  1203.     if (error)
  1204. #else
  1205.     if ((argc-- == 0) || error)
  1206. #endif
  1207.     {
  1208.         *pargc = argc;
  1209.         *pargv = argv;
  1210. #ifndef SFX
  1211.         if (G.vflag >= 2 && argc == -1) {              /* "unzip -v" */
  1212.             if (G.qflag > 3)                           /* "unzip -vqqqq" */
  1213.                 Info(slide, 0, ((char *)slide, "%d\n",
  1214.                   (UZ_MAJORVER*100 + UZ_MINORVER*10 + PATCHLEVEL)));
  1215.             else {
  1216.                 char *envptr, *getenv();
  1217.                 int numopts = 0;
  1218.  
  1219.                 Info(slide, 0, ((char *)slide, LoadFarString(UnzipUsageLine1v),
  1220.                   UZ_MAJORVER, UZ_MINORVER, PATCHLEVEL, BETALEVEL,
  1221.                   LoadFarStringSmall(VersionDate)));
  1222.                 Info(slide, 0, ((char *)slide,
  1223.                   LoadFarString(UnzipUsageLine2v)));
  1224.                 version(__G);
  1225.                 Info(slide, 0, ((char *)slide, LoadFarString(CompileOptions)));
  1226. #ifdef ASM_CRC
  1227.                 Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
  1228.                   LoadFarStringSmall(AsmCRC)));
  1229.                 ++numopts;
  1230. #endif
  1231. #ifdef ASM_INFLATECODES
  1232.                 Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
  1233.                   LoadFarStringSmall(AsmInflateCodes)));
  1234.                 ++numopts;
  1235. #endif
  1236. #ifdef CHECK_VERSIONS
  1237.                 Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
  1238.                   LoadFarStringSmall(Check_Versions)));
  1239.                 ++numopts;
  1240. #endif
  1241. #ifdef COPYRIGHT_CLEAN
  1242.                 Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
  1243.                   LoadFarStringSmall(Copyright_Clean)));
  1244.                 ++numopts;
  1245. #endif
  1246. #ifdef DEBUG
  1247.                 Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
  1248.                   LoadFarStringSmall(UDebug)));
  1249.                 ++numopts;
  1250. #endif
  1251. #ifdef DEBUG_TIME
  1252.                 Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
  1253.                   LoadFarStringSmall(DebugTime)));
  1254.                 ++numopts;
  1255. #endif
  1256. #ifdef DLL
  1257.                 Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
  1258.                   LoadFarStringSmall(Dll)));
  1259.                 ++numopts;
  1260. #endif
  1261. #ifdef DOSWILD
  1262.                 Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
  1263.                   LoadFarStringSmall(DosWild)));
  1264.                 ++numopts;
  1265. #endif
  1266. #ifdef LZW_CLEAN
  1267.                 Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
  1268.                   LoadFarStringSmall(LZW_Clean)));
  1269.                 ++numopts;
  1270. #endif
  1271. #ifndef MORE
  1272.                 Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
  1273.                   LoadFarStringSmall(No_More)));
  1274.                 ++numopts;
  1275. #endif
  1276. #ifdef NO_ZIPINFO
  1277.                 Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
  1278.                   LoadFarStringSmall(No_ZipInfo)));
  1279.                 ++numopts;
  1280. #endif
  1281. #ifdef NTSD_EAS
  1282.                 Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
  1283.                   LoadFarStringSmall(NTSDExtAttrib)));
  1284.                 ++numopts;
  1285. #endif
  1286. #ifdef OS2_EAS
  1287.                 Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
  1288.                   LoadFarStringSmall(OS2ExtAttrib)));
  1289.                 ++numopts;
  1290. #endif
  1291. #ifdef REENTRANT
  1292.                 Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
  1293.                   LoadFarStringSmall(Reentrant)));
  1294.                 ++numopts;
  1295. #endif
  1296. #ifdef REGARGS
  1297.                 Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
  1298.                   LoadFarStringSmall(RegArgs)));
  1299.                 ++numopts;
  1300. #endif
  1301. #ifdef RETURN_CODES
  1302.                 Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
  1303.                   LoadFarStringSmall(Return_Codes)));
  1304.                 ++numopts;
  1305. #endif
  1306. #ifdef TIMESTAMP
  1307.                 Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
  1308.                   LoadFarStringSmall(TimeStamp)));
  1309.                 ++numopts;
  1310. #endif
  1311. #ifdef UNIXBACKUP
  1312.                 Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
  1313.                   LoadFarStringSmall(UnixBackup)));
  1314.                 ++numopts;
  1315. #endif
  1316. #ifdef USE_EF_UT_TIME
  1317.                 Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
  1318.                   LoadFarStringSmall(Use_EF_UT_time)));
  1319.                 ++numopts;
  1320. #endif
  1321. #ifndef COPYRIGHT_CLEAN
  1322.                 Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
  1323.                   LoadFarStringSmall(Use_Smith_Code)));
  1324.                 ++numopts;
  1325. #endif
  1326. #ifndef LZW_CLEAN
  1327.                 Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
  1328.                   LoadFarStringSmall(Use_Unshrink)));
  1329.                 ++numopts;
  1330. #endif
  1331. #ifdef USE_VFAT
  1332.                 Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
  1333.                   LoadFarStringSmall(Use_VFAT_support)));
  1334.                 ++numopts;
  1335. #endif
  1336. #ifdef USE_ZLIB
  1337.                 sprintf((char *)(slide+256), LoadFarStringSmall(UseZlib),
  1338.                   ZLIB_VERSION, zlib_version);
  1339.                 Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
  1340.                   (char *)(slide+256)));
  1341.                 ++numopts;
  1342. #endif
  1343. #ifdef VMS_TEXT_CONV
  1344.                 Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
  1345.                   LoadFarStringSmall(VmsTextConv)));
  1346.                 ++numopts;
  1347. #endif
  1348. #ifdef VMSCLI
  1349.                 Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
  1350.                   LoadFarStringSmall(VmsCLI)));
  1351.                 ++numopts;
  1352. #endif
  1353. #ifdef VMSWILD
  1354.                 Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
  1355.                   LoadFarStringSmall(VmsWild)));
  1356.                 ++numopts;
  1357. #endif
  1358. #if CRYPT
  1359. # ifdef PASSWD_FROM_STDIN
  1360.                 Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
  1361.                   LoadFarStringSmall(PasswdStdin)));
  1362. # endif
  1363.                 Info(slide, 0, ((char *)slide, LoadFarString(Decryption),
  1364.                   CR_MAJORVER, CR_MINORVER, CR_BETA_VER,
  1365.                   LoadFarStringSmall(CryptDate)));
  1366.                 ++numopts;
  1367. #endif /* CRYPT */
  1368.                 if (numopts == 0)
  1369.                     Info(slide, 0, ((char *)slide,
  1370.                       LoadFarString(CompileOptFormat),
  1371.                       LoadFarStringSmall(None)));
  1372.  
  1373.                 Info(slide, 0, ((char *)slide, LoadFarString(EnvOptions)));
  1374.                 envptr = getenv(LoadFarStringSmall(EnvUnZip));
  1375.                 Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
  1376.                   LoadFarStringSmall(EnvUnZip),
  1377.                   (envptr == (char *)NULL || *envptr == 0)?
  1378.                   LoadFarStringSmall2(None) : envptr));
  1379.                 envptr = getenv(LoadFarStringSmall(EnvUnZip2));
  1380.                 Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
  1381.                   LoadFarStringSmall(EnvUnZip2),
  1382.                   (envptr == (char *)NULL || *envptr == 0)?
  1383.                   LoadFarStringSmall2(None) : envptr));
  1384.                 envptr = getenv(LoadFarStringSmall(EnvZipInfo));
  1385.                 Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
  1386.                   LoadFarStringSmall(EnvZipInfo),
  1387.                   (envptr == (char *)NULL || *envptr == 0)?
  1388.                   LoadFarStringSmall2(None) : envptr));
  1389.                 envptr = getenv(LoadFarStringSmall(EnvZipInfo2));
  1390.                 Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
  1391.                   LoadFarStringSmall(EnvZipInfo2),
  1392.                   (envptr == (char *)NULL || *envptr == 0)?
  1393.                   LoadFarStringSmall2(None) : envptr));
  1394. #ifndef __RSXNT__
  1395. #ifdef __EMX__
  1396.                 envptr = getenv(LoadFarStringSmall(EnvEMX));
  1397.                 Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
  1398.                   LoadFarStringSmall(EnvEMX),
  1399.                   (envptr == (char *)NULL || *envptr == 0)?
  1400.                   LoadFarStringSmall2(None) : envptr));
  1401.                 envptr = getenv(LoadFarStringSmall(EnvEMXOPT));
  1402.                 Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
  1403.                   LoadFarStringSmall(EnvEMXOPT),
  1404.                   (envptr == (char *)NULL || *envptr == 0)?
  1405.                   LoadFarStringSmall2(None) : envptr));
  1406. #endif /* __EMX__ */
  1407. #ifdef __GO32__
  1408.                 envptr = getenv(LoadFarStringSmall(EnvGO32));
  1409.                 Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
  1410.                   LoadFarStringSmall(EnvGO32),
  1411.                   (envptr == (char *)NULL || *envptr == 0)?
  1412.                   LoadFarStringSmall2(None) : envptr));
  1413.                 envptr = getenv(LoadFarStringSmall(EnvGO32TMP));
  1414.                 Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
  1415.                   LoadFarStringSmall(EnvGO32TMP),
  1416.                   (envptr == (char *)NULL || *envptr == 0)?
  1417.                   LoadFarStringSmall2(None) : envptr));
  1418. #endif /* __GO32__ */
  1419. #endif /* !__RSXNT__ */
  1420. #ifdef RISCOS
  1421.                 envptr = getenv(LoadFarStringSmall(EnvUnZipExts));
  1422.                 Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
  1423.                   LoadFarStringSmall(EnvUnZipExts),
  1424.                   (envptr == (char *)NULL || *envptr == 0)?
  1425.                   LoadFarStringSmall2(None) : envptr));
  1426. #endif /* RISCOS */
  1427.             }
  1428.             return 0;
  1429.         }
  1430.         if (!G.noargs && !error)
  1431.             error = PK_PARAM;   /* had options (not -h or -v) but no zipfile */
  1432. #endif /* !SFX */
  1433.         return USAGE(error);
  1434.     }
  1435.  
  1436. #ifdef SFX
  1437.     /* print our banner unless we're being fairly quiet */
  1438.     if (G.qflag < 2)
  1439.         Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXBanner),
  1440.           UZ_MAJORVER, UZ_MINORVER, PATCHLEVEL, BETALEVEL,
  1441.           LoadFarStringSmall(VersionDate)));
  1442. #ifdef BETA
  1443.     /* always print the beta warning:  no unauthorized distribution!! */
  1444.     Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(BetaVersion), "\n",
  1445.       "SFX"));
  1446. #endif
  1447. #endif /* SFX */
  1448.  
  1449.     if (G.cflag || G.tflag || G.vflag || G.zflag
  1450. #ifdef TIMESTAMP
  1451.                                                  || G.T_flag
  1452. #endif
  1453.                                                             )
  1454.         G.extract_flag = FALSE;
  1455.     else
  1456.         G.extract_flag = TRUE;
  1457.  
  1458. #if (!defined(SFX) || defined(SFX_EXDIR))
  1459.     if (G.dflag) {
  1460.         if (G.extract_flag) {
  1461.             G.create_dirs = !G.fflag;
  1462.             if ((error = checkdir(__G__ exdir, ROOT)) > 2)
  1463.                 return error;   /* out of memory, or file in way */
  1464.         } else /* -d ignored */
  1465.             Info(slide, 0x401, ((char *)slide, LoadFarString(NotExtracting)));
  1466.     }
  1467. #endif /* !SFX || SFX_EXDIR */
  1468.  
  1469.     *pargc = argc;
  1470.     *pargv = argv;
  1471.     return 0;
  1472.  
  1473. } /* end function uz_opts() */
  1474.  
  1475.  
  1476.  
  1477.  
  1478.  
  1479. /********************/
  1480. /* Function usage() */
  1481. /********************/
  1482.  
  1483. #ifdef SFX
  1484. #  ifdef VMS
  1485. #    define LOCAL "X.  Quote uppercase options"
  1486. #  endif
  1487. #  ifdef UNIX
  1488. #    define LOCAL "X"
  1489. #  endif
  1490. #  ifdef DOS_OS2_W32
  1491. #    define LOCAL "s$"
  1492. #  endif
  1493. #  ifdef AMIGA
  1494. #    define LOCAL "N"
  1495. #  endif
  1496.    /* Default for all other systems: */
  1497. #  ifndef LOCAL
  1498. #    define LOCAL ""
  1499. #  endif
  1500.  
  1501. #  ifdef MORE
  1502. #    define SFXOPT1 "M"
  1503. #  else
  1504. #    define SFXOPT1 ""
  1505. #  endif
  1506.  
  1507. int usage(__G__ error)   /* return PK-type error code */
  1508.     int error;
  1509.      __GDEF
  1510. {
  1511.     Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXBanner),
  1512.       UZ_MAJORVER, UZ_MINORVER, PATCHLEVEL, BETALEVEL,
  1513.       LoadFarStringSmall(VersionDate)));
  1514.     Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXOpts),
  1515.       SFXOPT1, LOCAL));
  1516. #ifdef BETA
  1517.     Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(BetaVersion), "\n",
  1518.       "SFX"));
  1519. #endif
  1520.  
  1521.     if (error)
  1522.         return PK_PARAM;
  1523.     else
  1524.         return PK_COOL;     /* just wanted usage screen: no error */
  1525.  
  1526. } /* end function usage() */
  1527.  
  1528.  
  1529.  
  1530.  
  1531.  
  1532. #else /* !SFX */
  1533. #  ifdef VMS
  1534. #    define QUOT '\"'
  1535. #    define QUOTS "\""
  1536. #  else
  1537. #    define QUOT ' '
  1538. #    define QUOTS ""
  1539. #  endif
  1540.  
  1541. int usage(__G__ error)   /* return PK-type error code */
  1542.     int error;
  1543.     __GDEF
  1544. {
  1545.     int flag = (error? 1 : 0);
  1546.  
  1547.  
  1548. /*---------------------------------------------------------------------------
  1549.     Print either ZipInfo usage or UnZip usage, depending on incantation.
  1550.     (Strings must be no longer than 512 bytes for Turbo C, apparently.)
  1551.   ---------------------------------------------------------------------------*/
  1552.  
  1553.     if (G.zipinfo_mode) {
  1554.  
  1555. #ifndef NO_ZIPINFO
  1556.  
  1557.         Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine1),
  1558.           ZI_MAJORVER, ZI_MINORVER, PATCHLEVEL, BETALEVEL,
  1559.           LoadFarStringSmall(VersionDate),
  1560.           LoadFarStringSmall2(ZipInfoExample), QUOTS,QUOTS));
  1561.         Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine2)));
  1562.         Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine3),
  1563.           QUOT,QUOT, QUOT,QUOT, LoadFarStringSmall(ZipInfoUsageLine4)));
  1564. #ifdef VMS
  1565.         Info(slide, flag, ((char *)slide, "\nRemember that non-lowercase\
  1566.  filespecs must be quoted in VMS (e.g., \"Makefile\").\n"));
  1567. #endif
  1568.  
  1569. #endif /* !NO_ZIPINFO */
  1570.  
  1571.     } else {   /* UnZip mode */
  1572.  
  1573.         Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine1),
  1574.           UZ_MAJORVER, UZ_MINORVER, PATCHLEVEL, BETALEVEL,
  1575.           LoadFarStringSmall(VersionDate)));
  1576. #ifdef BETA
  1577.         Info(slide, flag, ((char *)slide, LoadFarString(BetaVersion), "", ""));
  1578. #endif
  1579.  
  1580.         Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine2),
  1581.           ZIPINFO_MODE_OPTION, LoadFarStringSmall(ZipInfoMode)));
  1582. #ifdef VMS
  1583.         if (!error)  /* maybe no command-line tail found; show extra help */
  1584.             Info(slide, flag, ((char *)slide, LoadFarString(VMSusageLine2b)));
  1585. #endif
  1586.  
  1587.         Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine3),
  1588.           LoadFarStringSmall(local1)));
  1589.  
  1590.         Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine4),
  1591.           QUOT,QUOT, QUOT,QUOT, LoadFarStringSmall(local2), QUOT,QUOT,
  1592.           LoadFarStringSmall2(local3)));
  1593.  
  1594.         /* This is extra work for SMALL_MEM, but it will work since
  1595.          * LoadFarStringSmall2 uses the same buffer.  Remember, this
  1596.          * is a hack. */
  1597.         Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine5),
  1598.           LoadFarStringSmall(Example2), LoadFarStringSmall2(Example3),
  1599.           LoadFarStringSmall2(Example3)));
  1600.  
  1601.     } /* end if (G.zipinfo_mode) */
  1602.  
  1603.     if (error)
  1604.         return PK_PARAM;
  1605.     else
  1606.         return PK_COOL;     /* just wanted usage screen: no error */
  1607.  
  1608. } /* end function usage() */
  1609.  
  1610. #endif /* ?SFX */
  1611. #endif /* !WINDLL */
  1612.